package cn.tedu.ems.service.impl;

import cn.tedu.ems.pojo.entity.User;
import cn.tedu.ems.pojo.vo.Manager;
import cn.tedu.ems.pojo.vo.TokenUserVO;
import cn.tedu.ems.pojo.vo.UserVO;
import cn.tedu.response.ResponseResult;
import cn.tedu.ems.mapper.LoginMapper;
import cn.tedu.ems.pojo.dto.UserParam;

import cn.tedu.ems.service.LoginService;
import cn.tedu.response.StatusCode;
import cn.tedu.utils.JwtUtil;
import cn.tedu.utils.RedisUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Objects;

import static cn.tedu.response.StatusCode.LOGIN_SUCCESS;

@Slf4j
@Service
public class LoginServiceImpl implements LoginService {
    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    LoginMapper loginMapper;

    @Autowired
    private RedisUtil redisUtil;

    @Override
    public TokenUserVO login(UserParam userParam) {
        log.info("登录参数:{}", userParam);
        /**
         * 1.检查参数是否合法
         * 2.根据用户名和密码去数据库中查询是否存在
         * 3.如果不存在,或者是不一致,或者是状态禁用,那么就登录失败
         * 如果存在,使用使用JWT生成token,返回给前端
         * 5.token放入redis当中,在redis当中设置过期时间(登录的时候,首先验证token是否存在)
         */
        if (userParam.getUsername() == null || userParam.getPassword() == null) {
            throw new RuntimeException("用户名或密码不能为空");
        }
        String username = userParam.getUsername();
        String password = userParam.getPassword();
        //封装成Authentication对象
        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
                new UsernamePasswordAuthenticationToken(username, password);
        Authentication authenticate = authenticationManager.authenticate(usernamePasswordAuthenticationToken);
        //如果认证没有通过,抛异常,防御性编程
        if (Objects.isNull(authenticate)) {
            throw new RuntimeException("认证失败");
        }

        // 如果认证成功后，将认证信息存入SecurityContextHolder
        SecurityContextHolder.getContext().setAuthentication(authenticate);
        //这里获取authentication是从SecurityContextHolder中获取的,是已经认证过了的
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        // 检查认证信息是否可用
        if (authentication == null || !authentication.isAuthenticated()) {
            throw new IllegalStateException("没有可用的身份验证信息");
        }

        //从认证信息Userdetails中获取用户详情
        Object principal = authentication.getPrincipal();
        String authenticateUsername = null;

        // 检查principal是否为UserDetails类型
        if (principal instanceof UserDetails) {
            UserDetails userDetails = (UserDetails) principal;
            authenticateUsername = userDetails.getUsername();
        } else {
            // 如果不是UserDetails类型，直接获取用户名
            authenticateUsername = principal.toString();
        }
        // 使用用户名生成JWT
//        String token = JwtUtil.createJWT(authenticateUsername);
        //获取用户id
        QueryWrapper<UserVO> userQueryWrapper = new QueryWrapper<>();
        //根据用户名查询id
        userQueryWrapper.select("id", "username", "password", "status", "create_time", "update_time", "delete_time");
        //软删除,delete_time不为NUll的会被视为已删除
        userQueryWrapper.isNull("delete_time");
        userQueryWrapper.eq("username", username);
        UserVO userVO = loginMapper.selectOne(userQueryWrapper);
        String token = JwtUtil.createJWT(userVO.toJson());
        Integer id = userVO.getId();
        log.debug("这是一个用户id:{}", id);
        String userId = id.toString();
        //一个用户对应一个token
        redisUtil.set("login:" + userId, token);
        //设置过期时间为一分钟
        redisUtil.expire("login:" + userId, 12000);
        //将redis中的token取出来打印一下
        log.debug("redis中的token:{}", redisUtil.get("login:" + userId));
        userVO.setToken(token);
        log.debug("查询到的用户数据:{}", userVO);
        TokenUserVO tokenUserVO = new TokenUserVO();
        BeanUtils.copyProperties(userVO, tokenUserVO);
        log.debug("这是要返回的数据tokenUserVO:{}", tokenUserVO);
        getManagerByToken(token);
        //返回登录成功
        return tokenUserVO;
    }


    @Override
    public ResponseResult loginOut(String userId) {
        log.debug("登出:{}", redisUtil.get("login:" + userId));
        //这里要删除redis中的token,根据前端传递过来的用户id
        redisUtil.del("login:" + userId);
        log.debug("现在已经移除了:{}", redisUtil.get("login:" + userId));
        //登出成功
        return ResponseResult.ok(StatusCode.OPERATION_SUCCESS);
    }


    public Manager getManagerByToken(String token) {
        try {
            Claims claims = JwtUtil.parseJWT(token);
            UserVO userVO = UserVO.formJson(claims.getSubject());
            Manager manager = new Manager();
            BeanUtils.copyProperties(userVO, manager);
            log.debug("这是解析出来的数据:{}", claims.getSubject());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return null;
    }


}
